﻿// -----------------------------------------------------------------------
// <copyright file="DeflateDecompressor.cs">
// Copyright (c) 2013 Andrey Veselov. All rights reserved.
// License:  Microsoft Public License (MS-PL)
// Contacts: http://andrey.moveax.com  andrey@moveax.com
// </copyright>
// -----------------------------------------------------------------------

namespace PortableImagingLibrary.Png.Compressors
{
    using Exceptions;
    using Ionic.Zlib;
    using System;

    internal class DeflateDecompressor : IDecompressor
    {
        private int _bytesPerLine;
        // ReSharper disable RedundantDefaultFieldInitializer
        private bool _disposed = false;
        // ReSharper restore RedundantDefaultFieldInitializer

        private readonly BufferStream _bufferStream;
        private readonly ZlibStream _zlibStream;

        public byte[] OutputBuffer { get; private set; }

        public int BytesPerLine
        {
            get { return this._bytesPerLine; }
            set
            {
                this._bytesPerLine = value;
                this.OutputBuffer = new byte[value];
            }
        }

        public DeflateDecompressor()
        {
            this._bufferStream = new BufferStream();
            this._zlibStream = new ZlibStream(this._bufferStream, CompressionMode.Decompress);
        }

        ~DeflateDecompressor()
        {
            this.Dispose(false);
        }

        #region ICompressor Members

        public void SetCurrentChunkData(byte[] data)
        {
            if (this._disposed)
                throw new ObjectDisposedException("DeflateDecompressor");

            this._bufferStream.UpdateBuffer(data);
        }

        public bool ReadLine()
        {
            if (this._disposed)
                throw new ObjectDisposedException("DeflateDecompressor");

            var readed = this._zlibStream.Read(this.OutputBuffer, 0, this.BytesPerLine);

            if (readed != this.BytesPerLine && readed != 0)
                throw new InvalidImageFormatException("Invalid data size.");

            return readed != 0;
        }

        #endregion ICompressor Members

        #region IDisposable Members

        public void Dispose()
        {
            this.Dispose(true);

            GC.SuppressFinalize(this);
        }

        #endregion IDisposable Members

        private void Dispose(bool disposing)
        {
            if (this._disposed && !disposing)
                return;

            this._bufferStream.Dispose();
            this._zlibStream.Dispose();
            this._disposed = true;
        }
    }
}
